/**************************************************************************************************
* Title: SumAlign.h
* Author: Gael Huber
* Description: Represents the alignment of a particular block of memory being allocated.
**************************************************************************************************/
#ifndef __SUMALIGN_H__
#define __SUMALIGN_H__

#include <malloc.h>

#define ALIGN16 __declspec(align(16))

// Memory aligned malloc
static inline void* aligned_malloc(size_t size, int alignment) {
	const int pointerSize = sizeof(void*);
	const int requestedSize = size + alignment - 1 + pointerSize;
	void* raw = malloc(requestedSize);
	void* start = (char*) raw + pointerSize;
	void* aligned = (void*)(((unsigned int)((char*)start + alignment - 1)) & ~(alignment - 1));
	*(void**)((char*)aligned - pointerSize) = raw;
	return aligned;
}

// Memory-aligned free
static inline void aligned_free(void* mem) {
	void* raw = *(void**)((char*)mem - sizeof(void*));
	free(raw);
}

#define DYNAMIC_ALIGNMENT(T) \
	/* Non-aligned version of new */ \
	inline void* operator new(size_t size) \
	{ \
		return aligned_malloc(size, __alignof(T)); \
	} \
	/* Aligned version of new */ \
	inline void* operator new (size_t size, int alignment) { \
		return aligned_malloc(size, alignment); \
	} \
	/* Non-aligned version of new[] */ \
	inline void* operator new[] (size_t size) { \
		return aligned_malloc(size, __alignof(T)); \
	} \
	/* Aligned version of new[] */ \
	inline void* operator new[] (size_t size, int alignment) { \
		return aligned_malloc(size, alignment); \
	} \
	/* Aligned version of delete */ \
	inline void operator delete(void* mem) { \
		aligned_free(mem); \
	} \
	/* Aligned version of free */ \
	inline void operator delete[] (void* mem) { \
		aligned_free(mem); \
	}

#endif